package plp.orientadaObjetos2.comando;

import java.util.ArrayList;

import plp.orientadaObjetos1.comando.Atribuicao;
import plp.orientadaObjetos1.excecao.declaracao.ClasseNaoDeclaradaException;
import plp.orientadaObjetos1.excecao.declaracao.VariavelNaoDeclaradaException;
import plp.orientadaObjetos1.expressao.Expressao;
import plp.orientadaObjetos1.expressao.leftExpression.Id;
import plp.orientadaObjetos1.expressao.leftExpression.LeftExpression;
import plp.orientadaObjetos1.memoria.DefClasse;
import plp.orientadaObjetos1.util.Tipo;
import plp.orientadaObjetos1.util.TipoClasse;
import plp.orientadaObjetos2.memoria.AmbienteCompilacaoOO2;
import plp.orientadaObjetos2.util.SuperClasseMap;

public class AtribuicaoOO2 extends Atribuicao {

	public AtribuicaoOO2(LeftExpression av, Expressao expressao) {
		super(av, expressao);		
	}


	/* (non-Javadoc)
	 * @see plp.orientadaObjetos1.comando.Comando#checaTipo(plp.orientadaObjetos1.memoria.AmbienteCompilacao)
	 */
	public boolean checaTipo(AmbienteCompilacaoOO2 ambiente) throws VariavelNaoDeclaradaException, ClasseNaoDeclaradaException {
		boolean atribuicao = false;

		if ((getExpressao().getTipo(ambiente) instanceof TipoClasse) &&
				(getExpressao().getTipo(ambiente) instanceof TipoClasse)) {	

			Tipo esquerda = ambiente.getTipo(getAv().getId());
			Tipo direita  = getExpressao().getTipo(ambiente);

			DefClasse classeEsquerda = ambiente.getDefClasse(esquerda.getTipo());
			DefClasse classeDireita = ambiente.getDefClasse(direita.getTipo());

			try {
				ArrayList<SuperClasseMap> arraySuperClasses = ((AmbienteCompilacaoOO2)ambiente).getSuperClasse(classeDireita.getIdClasse());
				for(int i=0; i < arraySuperClasses.size(); i++){
					Id idSuperClasse = arraySuperClasses.get(i).getSuperClasse();
					DefClasse superClasse = ambiente.getDefClasse(idSuperClasse);
					while ( !arraySuperClasses.isEmpty()) {
						if (superClasse.equals(classeEsquerda)) {
							atribuicao = true;
							break;
						}
						arraySuperClasses = ((AmbienteCompilacaoOO2)ambiente).getSuperClasse(superClasse.getIdClasse());
					}
				}
			} catch (NullPointerException e) {
				return false;
			}
		}

		return (getExpressao().checaTipo(ambiente)
				&& (getAv().getTipo(ambiente).equals(getExpressao().getTipo(ambiente))
						|| getExpressao().getTipo(ambiente).equals(TipoClasse.TIPO_NULL)))
						|| atribuicao;


	}



}




